package com.ruicar.afs.cloud.afscase.loanapprove.service.impl;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.afscase.approvetask.entity.CaseApproveRecord;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkProcessScheduleInfo;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkTaskPool;
import com.ruicar.afs.cloud.afscase.approvetask.service.CaseApproveRecordService;
import com.ruicar.afs.cloud.afscase.approvetask.service.WorkProcessScheduleInfoService;
import com.ruicar.afs.cloud.afscase.approvetask.service.WorkTaskPoolService;

import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseContractInfoService;
import com.ruicar.afs.cloud.afscase.loanapprove.condition.LoanApproveCondition;
import com.ruicar.afs.cloud.afscase.loanapprove.service.LoanWorkflowService;
import com.ruicar.afs.cloud.afscase.processor.enums.LoanSubmitEnum;
import com.ruicar.afs.cloud.afscase.processor.service.LoanApproveWorkflowService;
import com.ruicar.afs.cloud.afscase.processor.service.LoanGpsAuditWorkflowService;
import com.ruicar.afs.cloud.afscase.processor.vo.LoanBusinessDataVO;
import com.ruicar.afs.cloud.afscase.processor.vo.NormalTaskSubmitVO;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.security.service.AfsUser;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.ApplyStatusEnum;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.FlowNodeEnum;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.UseSceneEnum;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.WhetherEnum;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.FLowGiveUpRequest;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * @author yk.Li
 * @Date 2020/7/17
 * @description
 */
@Service
@AllArgsConstructor
@Data
@Slf4j
public class LoanWorkflowServiceImpl implements LoanWorkflowService {
    //工作流service
    private LoanApproveWorkflowService loanApproveWorkflowService;
    private WorkProcessScheduleInfoService workProcessScheduleInfoService;
    private WorkTaskPoolService workTaskPoolService;
    private LoanGpsAuditWorkflowService loanGpsAuditWorkflowService;
    private CaseContractInfoService caseContractInfoService;
    private CaseApproveRecordService caseApproveRecordService;

    @Transactional
    @Override
    public void submitWorkflow(LoanApproveCondition condition) {
        WorkTaskPool pool = workTaskPoolService.getOne(Wrappers.<WorkTaskPool>lambdaQuery()
                .eq(StringUtils.isNotBlank(condition.getContractNo()), WorkTaskPool::getContractNo, condition.getContractNo())
                .eq(StringUtils.isNotBlank(condition.getUseScene()), WorkTaskPool::getProcessType, condition.getUseScene()), false);
        if (null == pool) {
            log.error("任务池未找到该数据");
        }
        CaseApproveRecord caseApproveRecord = updateApproveRecord(condition, pool);
        WorkProcessScheduleInfo info = workProcessScheduleInfoService.getById(Long.parseLong(caseApproveRecord.getStageId()));

        //流程分支条件参数
        LoanBusinessDataVO loanBusinessDataVO = LoanBusinessDataVO.builder()
                .assigned(WhetherEnum.NO.getCode())
                .build();
        log.info("----------工作流提交开始-------->");
        loanApproveWorkflowService.submit(NormalTaskSubmitVO.builder()
                .record(caseApproveRecord)
                .workFlowInfo(info)
                .workTaskPool(pool)
                .autoFlag(condition.getAutoFlag())
                .loanBusinessDataVO(loanBusinessDataVO)
                .build());
        log.info("----------工作流提交完成-------->");
    }

    /**
     * @param
     * @description 强制结束流程
     * @author yk.Li
     * @date 2020/8/1
     */
    @Override
    public void giveUpWorkflow(String contractNo,String useScene) {
        log.info("----------工作流结束开始-------->");
        WorkProcessScheduleInfo info = getWorkProcessScheduleInfo(contractNo,useScene);
        if (ObjectUtils.isNotEmpty(info)) {
            FLowGiveUpRequest fLowGiveUpRequest = new FLowGiveUpRequest();
            fLowGiveUpRequest.setFlowInstanceId(info.getStageId());
            loanApproveWorkflowService.flowGiveUp(fLowGiveUpRequest);
            workProcessScheduleInfoService.removeById(info);
        }
        log.info("----------工作流结束完成-------->");
    }

    @Transactional
    @Override
    public void submitWorkflowByScheduleInfo(LoanApproveCondition condition) {
        WorkTaskPool pool = workTaskPoolService.getOne(Wrappers.<WorkTaskPool>lambdaQuery()
                .eq(StringUtils.isNotBlank(condition.getContractNo()), WorkTaskPool::getContractNo, condition.getContractNo())
                .eq(StringUtils.isNotBlank(condition.getUseScene()), WorkTaskPool::getProcessType, condition.getUseScene()), false);
        WorkProcessScheduleInfo info = getWorkProcessScheduleInfo(condition.getContractNo(), condition.getUseScene());
        if(ObjectUtils.isNotEmpty(info)){
            CaseApproveRecord caseApproveRecord = updateApproveRecord(condition, pool);

            //流程分支条件参数
            /**如果指定处理人，补件回复需要设置为指定处理人 add by fangchenliang*/
            LoanBusinessDataVO loanBusinessDataVO = null;
            if(StringUtils.isNotBlank(info.getAppointHandler())){
                loanBusinessDataVO=LoanBusinessDataVO.builder()
                        .assigned(WhetherEnum.YES.getCode())
                        .build();
            }else{
                loanBusinessDataVO=LoanBusinessDataVO.builder()
                        .assigned(WhetherEnum.NO.getCode())
                        .build();
            }
            log.info("----------工作流提交开始-------->");
            loanApproveWorkflowService.submit(NormalTaskSubmitVO.builder()
                    .record(caseApproveRecord)
                    .workFlowInfo(info)
                    .workTaskPool(pool)
                    .autoFlag(condition.getAutoFlag())
                    .loanBusinessDataVO(loanBusinessDataVO)
                    .build());
            log.info("----------工作流提交完成-------->");
        }
    }

    @Transactional
    @Override
    public void gpsSubmitWorkflowByScheduleInfo(LoanApproveCondition condition) {
        WorkProcessScheduleInfo info = getWorkProcessScheduleInfo(condition.getContractNo(), condition.getUseScene());
        WorkTaskPool pool = workTaskPoolService.getOne(Wrappers.<WorkTaskPool>lambdaQuery()
                .eq(StringUtils.isNotBlank(condition.getContractNo()), WorkTaskPool::getContractNo, condition.getContractNo())
                .eq(StringUtils.isNotBlank(condition.getUseScene()), WorkTaskPool::getProcessType, condition.getUseScene()), false);
        if(ObjectUtils.isNotEmpty(info)){
            CaseApproveRecord caseApproveRecord = updateApproveRecord(condition, pool);

            log.info("----------工作流提交开始-------->");
            loanGpsAuditWorkflowService.submit(NormalTaskSubmitVO.builder()
                    .record(caseApproveRecord)
                    .workFlowInfo(info)
                    .autoFlag(condition.getAutoFlag())
                    .build());
            log.info("----------工作流提交完成-------->");
        }
    }

    public WorkProcessScheduleInfo getWorkProcessScheduleInfo(String contractNo,String useSceneEnum) {
        WorkTaskPool pool = workTaskPoolService.getOne(Wrappers.<WorkTaskPool>lambdaQuery()
                .eq(StringUtils.isNotBlank(contractNo), WorkTaskPool::getContractNo, contractNo)
                .eq(StringUtils.isNotBlank(useSceneEnum), WorkTaskPool::getProcessType, useSceneEnum), false);
        if(ObjectUtils.isNotEmpty(pool)){
            return workProcessScheduleInfoService.getOne(Wrappers.<WorkProcessScheduleInfo>lambdaQuery()
                    .eq(StringUtils.isNotBlank(pool.getStageId()), WorkProcessScheduleInfo::getId, Long.parseLong(pool.getStageId())), false);
        } else {
            return new WorkProcessScheduleInfo();
        }
    }

    private CaseApproveRecord updateApproveRecord(LoanApproveCondition condition, WorkTaskPool pool) {
        CaseApproveRecord caseApproveRecord = caseApproveRecordService.getOne(Wrappers.<CaseApproveRecord>lambdaQuery()
                .eq(CaseApproveRecord::getTaskId,pool.getId().toString())
                .eq(StringUtils.isNotBlank(condition.getContractNo()),CaseApproveRecord::getContractNo,condition.getContractNo()),false);
        if(ObjectUtils.isEmpty(caseApproveRecord)){
            caseApproveRecord=new CaseApproveRecord();
            caseApproveRecord.setStageId(pool.getStageId());
            caseApproveRecord.setDisposeStaff(pool.getApproveStaffName());
            caseApproveRecord.setApplyNo(pool.getApplyNo());
            caseApproveRecord.setContractNo(pool.getContractNo());
            caseApproveRecord.setApproveStartTime(new Date());
            caseApproveRecord.setUseScene(pool.getProcessType()==null? UseSceneEnum.GENERAL_LOAN.getValue():pool.getProcessType());
            caseApproveRecord.setDisposeNodeName(pool.getTaskNodeName());
            caseApproveRecord.setDisposeNode(pool.getTaskNodeId());
            caseApproveRecord.setTaskId(pool.getId().toString());
            caseApproveRecordService.save(caseApproveRecord);
        }

        caseApproveRecord.setApproveSuggest(condition.getApproveSuggest());
        if(null != condition.getApproveSuggest()){
            caseApproveRecord.setApproveSuggestName(AfsEnumUtil.desc(AfsEnumUtil.getEnum(condition.getApproveSuggest(), LoanSubmitEnum.class)));
        }
        caseApproveRecord.setApproveEndTime(new Date());
        caseApproveRecord.setApproveMessage(condition.getApproveRemark());
        caseApproveRecord.setApproveRemark(condition.getApproveRemark());
        caseApproveRecord.setApproveType(condition.getApproveType());
        caseApproveRecord.setFlowNode(condition.getFlowNode());
        return caseApproveRecord;
    }
}
